using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Text.Json;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services.Notification
{
    /// <summary>
    /// 短信发送结果
    /// </summary>
    public class SmsSendResult
    {
        public bool Success { get; set; }
        public string? MessageId { get; set; }
        public string? ErrorMessage { get; set; }
        public DateTime SentAt { get; set; }
        public string? Provider { get; set; }
        public decimal? Cost { get; set; }
    }

    /// <summary>
    /// 批量短信发送结果
    /// </summary>
    public class SmsBatchSendResult
    {
        public int TotalCount { get; set; }
        public int SuccessCount { get; set; }
        public int FailureCount { get; set; }
        public List<SmsSendResult> Results { get; set; } = new();
        public TimeSpan TotalTime { get; set; }
        public decimal TotalCost { get; set; }
    }

    /// <summary>
    /// 短信消息模型
    /// </summary>
    public class SmsMessage
    {
        /// <summary>
        /// 手机号码（国际格式，如+86138****1234）
        /// </summary>
        public string PhoneNumber { get; set; } = string.Empty;

        /// <summary>
        /// 短信内容
        /// </summary>
        public string Content { get; set; } = string.Empty;

        /// <summary>
        /// 模板ID（用于模板短信）
        /// </summary>
        public string? TemplateId { get; set; }

        /// <summary>
        /// 模板参数（用于模板短信）
        /// </summary>
        public Dictionary<string, string> TemplateParams { get; set; } = new();

        /// <summary>
        /// 短信签名
        /// </summary>
        public string? SignName { get; set; }

        /// <summary>
        /// 优先级（0=低, 1=普通, 2=高, 3=紧急）
        /// </summary>
        public int Priority { get; set; } = 1;

        /// <summary>
        /// 扩展字段
        /// </summary>
        public Dictionary<string, object> ExtendedProperties { get; set; } = new();
    }

    /// <summary>
    /// 短信服务配置
    /// </summary>
    public class SmsServiceOptions
    {
        public const string SectionName = "SmsService";

        /// <summary>
        /// 默认提供商 (aliyun, tencent, huawei)
        /// </summary>
        public string DefaultProvider { get; set; } = "aliyun";

        /// <summary>
        /// 是否启用故障转移
        /// </summary>
        public bool EnableFailover { get; set; } = true;

        /// <summary>
        /// 重试次数
        /// </summary>
        public int RetryCount { get; set; } = 2;

        /// <summary>
        /// 重试间隔（秒）
        /// </summary>
        public int RetryIntervalSeconds { get; set; } = 3;

        /// <summary>
        /// 是否启用频率限制
        /// </summary>
        public bool EnableRateLimit { get; set; } = true;

        /// <summary>
        /// 每分钟最大发送数量（防止滥用）
        /// </summary>
        public int MaxSendPerMinute { get; set; } = 60;

        /// <summary>
        /// 同一手机号每小时最大发送数量
        /// </summary>
        public int MaxSendPerHourPerPhone { get; set; } = 10;

        /// <summary>
        /// 阿里云短信配置
        /// </summary>
        public AliyunSmsSettings Aliyun { get; set; } = new();

        /// <summary>
        /// 腾讯云短信配置
        /// </summary>
        public TencentSmsSettings Tencent { get; set; } = new();

        /// <summary>
        /// 华为云短信配置
        /// </summary>
        public HuaweiSmsSettings Huawei { get; set; } = new();
    }

    public class AliyunSmsSettings
    {
        public string AccessKeyId { get; set; } = string.Empty;
        public string AccessKeySecret { get; set; } = string.Empty;
        public string Region { get; set; } = "cn-hangzhou";
        public string SignName { get; set; } = string.Empty;
    }

    public class TencentSmsSettings
    {
        public string SecretId { get; set; } = string.Empty;
        public string SecretKey { get; set; } = string.Empty;
        public string Region { get; set; } = "ap-beijing";
        public string SdkAppId { get; set; } = string.Empty;
        public string SignName { get; set; } = string.Empty;
    }

    public class HuaweiSmsSettings
    {
        public string AccessKeyId { get; set; } = string.Empty;
        public string SecretAccessKey { get; set; } = string.Empty;
        public string Region { get; set; } = "cn-north-4";
        public string ProjectId { get; set; } = string.Empty;
        public string ChannelNumber { get; set; } = string.Empty;
        public string SignName { get; set; } = string.Empty;
    }

    /// <summary>
    /// 短信服务接口
    /// </summary>
    public interface ISmsService
    {
        /// <summary>
        /// 发送单条短信
        /// </summary>
        Task<SmsSendResult> SendAsync(SmsMessage message);

        /// <summary>
        /// 使用模板发送短信
        /// </summary>
        Task<SmsSendResult> SendTemplateAsync(string templateId, Dictionary<string, string> templateParams, string phoneNumber, string? signName = null);

        /// <summary>
        /// 批量发送短信
        /// </summary>
        Task<SmsBatchSendResult> SendBatchAsync(List<SmsMessage> messages);

        /// <summary>
        /// 发送验证码短信
        /// </summary>
        Task<SmsSendResult> SendVerificationCodeAsync(string phoneNumber, string code, int expireMinutes = 5);

        /// <summary>
        /// 测试短信服务连接
        /// </summary>
        Task<bool> TestConnectionAsync(string? provider = null);

        /// <summary>
        /// 获取支持的提供商列表
        /// </summary>
        List<string> GetSupportedProviders();

        /// <summary>
        /// 查询短信发送状态
        /// </summary>
        Task<SmsSendResult> QuerySendStatusAsync(string messageId, string? provider = null);
    }

    /// <summary>
    /// 短信提供商接口
    /// </summary>
    public interface ISmsProvider
    {
        string Name { get; }
        bool IsConfigured { get; }
        Task<SmsSendResult> SendAsync(SmsMessage message);
        Task<SmsSendResult> SendTemplateAsync(string templateId, Dictionary<string, string> templateParams, string phoneNumber, string? signName = null);
        Task<bool> TestConnectionAsync();
        Task<SmsSendResult> QuerySendStatusAsync(string messageId);
    }

    /// <summary>
    /// 企业级短信服务实现
    /// 支持多提供商、频率限制、自动故障转移、重试机制等功能
    /// </summary>
    public class SmsService : ISmsService
    {
        private readonly ILogger<SmsService> _logger;
        private readonly SmsServiceOptions _options;
        private readonly Dictionary<string, ISmsProvider> _providers;
        private readonly Dictionary<string, List<DateTime>> _rateLimitTracker;
        private readonly Dictionary<string, List<DateTime>> _phoneRateLimitTracker;
        private readonly object _rateLimitLock = new object();

        public SmsService(
            ILogger<SmsService> logger,
            IOptions<SmsServiceOptions> options)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
            
            _providers = new Dictionary<string, ISmsProvider>();
            _rateLimitTracker = new Dictionary<string, List<DateTime>>();
            _phoneRateLimitTracker = new Dictionary<string, List<DateTime>>();
            
            InitializeProviders();
        }

        /// <summary>
        /// 初始化短信提供商
        /// </summary>
        private void InitializeProviders()
        {
            try
            {
                // 阿里云短信提供商
                if (!string.IsNullOrEmpty(_options.Aliyun.AccessKeyId))
                {
                    _providers["aliyun"] = new AliyunSmsProvider(_options.Aliyun, _logger);
                }

                // 腾讯云短信提供商
                if (!string.IsNullOrEmpty(_options.Tencent.SecretId))
                {
                    _providers["tencent"] = new TencentSmsProvider(_options.Tencent, _logger);
                }

                // 华为云短信提供商
                if (!string.IsNullOrEmpty(_options.Huawei.AccessKeyId))
                {
                    _providers["huawei"] = new HuaweiSmsProvider(_options.Huawei, _logger);
                }

                _logger.LogInformation("短信服务初始化完成，可用提供商: {Providers}", string.Join(", ", _providers.Keys));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "初始化短信提供商失败");
                throw;
            }
        }

        /// <summary>
        /// 发送单条短信
        /// </summary>
        public async Task<SmsSendResult> SendAsync(SmsMessage message)
        {
            if (message == null)
                throw new ArgumentNullException(nameof(message));

            if (string.IsNullOrEmpty(message.PhoneNumber))
                throw new ArgumentException("手机号码不能为空", nameof(message));

            if (string.IsNullOrEmpty(message.Content) && string.IsNullOrEmpty(message.TemplateId))
                throw new ArgumentException("短信内容或模板ID不能为空", nameof(message));

            // 检查频率限制
            if (!CheckRateLimit(message.PhoneNumber))
            {
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = "发送频率超出限制",
                    SentAt = DateTime.UtcNow
                };
            }

            var startTime = DateTime.UtcNow;
            var providers = GetOrderedProviders();

            foreach (var provider in providers)
            {
                if (!provider.IsConfigured)
                {
                    _logger.LogWarning("短信提供商 {Provider} 未正确配置，跳过", provider.Name);
                    continue;
                }

                try
                {
                    var result = await SendWithRetry(provider, message);
                    if (result.Success)
                    {
                        result.Provider = provider.Name;
                        var duration = DateTime.UtcNow - startTime;
                        
                        // 记录发送成功
                        RecordSendAttempt(message.PhoneNumber);
                        
                        _logger.LogInformation(
                            "短信发送成功 - 提供商: {Provider}, 手机号: {Phone}, 耗时: {Duration}ms",
                            provider.Name, MaskPhoneNumber(message.PhoneNumber), duration.TotalMilliseconds);
                        
                        return result;
                    }
                    
                    _logger.LogWarning("短信提供商 {Provider} 发送失败: {Error}", provider.Name, result.ErrorMessage);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "短信提供商 {Provider} 发送异常", provider.Name);
                    
                    if (!_options.EnableFailover || providers.Count == 1)
                    {
                        return new SmsSendResult
                        {
                            Success = false,
                            ErrorMessage = ex.Message,
                            SentAt = DateTime.UtcNow,
                            Provider = provider.Name
                        };
                    }
                }
            }

            return new SmsSendResult
            {
                Success = false,
                ErrorMessage = "所有短信提供商都发送失败",
                SentAt = DateTime.UtcNow
            };
        }

        /// <summary>
        /// 使用模板发送短信
        /// </summary>
        public async Task<SmsSendResult> SendTemplateAsync(string templateId, Dictionary<string, string> templateParams, string phoneNumber, string? signName = null)
        {
            var message = new SmsMessage
            {
                PhoneNumber = phoneNumber,
                TemplateId = templateId,
                TemplateParams = templateParams,
                SignName = signName
            };

            return await SendAsync(message);
        }

        /// <summary>
        /// 批量发送短信
        /// </summary>
        public async Task<SmsBatchSendResult> SendBatchAsync(List<SmsMessage> messages)
        {
            if (messages == null || messages.Count == 0)
                throw new ArgumentException("短信列表不能为空", nameof(messages));

            var result = new SmsBatchSendResult
            {
                TotalCount = messages.Count
            };

            var startTime = DateTime.UtcNow;
            var semaphore = new SemaphoreSlim(Environment.ProcessorCount); // 控制并发数
            var tasks = messages.Select(async message =>
            {
                await semaphore.WaitAsync();
                try
                {
                    var sendResult = await SendAsync(message);
                    lock (result)
                    {
                        result.Results.Add(sendResult);
                        if (sendResult.Success)
                        {
                            result.SuccessCount++;
                            if (sendResult.Cost.HasValue)
                                result.TotalCost += sendResult.Cost.Value;
                        }
                        else
                        {
                            result.FailureCount++;
                        }
                    }
                }
                finally
                {
                    semaphore.Release();
                }
            });

            await Task.WhenAll(tasks);
            result.TotalTime = DateTime.UtcNow - startTime;

            _logger.LogInformation(
                "批量短信发送完成 - 总数: {Total}, 成功: {Success}, 失败: {Failure}, 耗时: {Duration}ms, 总费用: {Cost}",
                result.TotalCount, result.SuccessCount, result.FailureCount, result.TotalTime.TotalMilliseconds, result.TotalCost);

            return result;
        }

        /// <summary>
        /// 发送验证码短信
        /// </summary>
        public async Task<SmsSendResult> SendVerificationCodeAsync(string phoneNumber, string code, int expireMinutes = 5)
        {
            var message = new SmsMessage
            {
                PhoneNumber = phoneNumber,
                Content = $"您的验证码是：{code}，{expireMinutes}分钟内有效。请勿泄露给他人。",
                Priority = 2, // 验证码使用高优先级
                ExtendedProperties = new Dictionary<string, object>
                {
                    ["MessageType"] = "VerificationCode",
                    ["Code"] = code,
                    ["ExpireMinutes"] = expireMinutes
                }
            };

            return await SendAsync(message);
        }

        /// <summary>
        /// 测试短信服务连接
        /// </summary>
        public async Task<bool> TestConnectionAsync(string? provider = null)
        {
            try
            {
                if (!string.IsNullOrEmpty(provider))
                {
                    if (_providers.TryGetValue(provider.ToLower(), out var specificProvider))
                    {
                        return await specificProvider.TestConnectionAsync();
                    }
                    return false;
                }

                // 测试所有提供商
                var results = await Task.WhenAll(
                    _providers.Values.Select(p => p.TestConnectionAsync())
                );

                return results.Any(r => r);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "测试短信服务连接失败");
                return false;
            }
        }

        /// <summary>
        /// 获取支持的提供商列表
        /// </summary>
        public List<string> GetSupportedProviders()
        {
            return _providers.Keys.ToList();
        }

        /// <summary>
        /// 查询短信发送状态
        /// </summary>
        public async Task<SmsSendResult> QuerySendStatusAsync(string messageId, string? provider = null)
        {
            if (string.IsNullOrEmpty(messageId))
                throw new ArgumentException("消息ID不能为空", nameof(messageId));

            try
            {
                var targetProviders = string.IsNullOrEmpty(provider)
                    ? _providers.Values.ToList()
                    : _providers.TryGetValue(provider.ToLower(), out var p) ? new List<ISmsProvider> { p } : new List<ISmsProvider>();

                foreach (var smsProvider in targetProviders)
                {
                    try
                    {
                        var result = await smsProvider.QuerySendStatusAsync(messageId);
                        if (result.Success || !string.IsNullOrEmpty(result.ErrorMessage))
                        {
                            result.Provider = smsProvider.Name;
                            return result;
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "提供商 {Provider} 查询消息状态失败", smsProvider.Name);
                    }
                }

                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = "未找到指定消息ID的状态信息",
                    SentAt = DateTime.UtcNow
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "查询短信发送状态失败 - 消息ID: {MessageId}", messageId);
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    SentAt = DateTime.UtcNow
                };
            }
        }

        #region 私有方法

        /// <summary>
        /// 检查频率限制
        /// </summary>
        private bool CheckRateLimit(string phoneNumber)
        {
            if (!_options.EnableRateLimit)
                return true;

            lock (_rateLimitLock)
            {
                var now = DateTime.UtcNow;

                // 清理过期记录
                CleanupExpiredRecords(now);

                // 检查全局频率限制
                var providerKey = "global";
                if (!_rateLimitTracker.ContainsKey(providerKey))
                    _rateLimitTracker[providerKey] = new List<DateTime>();

                var recentSends = _rateLimitTracker[providerKey];
                if (recentSends.Count >= _options.MaxSendPerMinute)
                {
                    _logger.LogWarning("全局发送频率超出限制，每分钟最大: {Limit}", _options.MaxSendPerMinute);
                    return false;
                }

                // 检查单个手机号频率限制
                if (!_phoneRateLimitTracker.ContainsKey(phoneNumber))
                    _phoneRateLimitTracker[phoneNumber] = new List<DateTime>();

                var phoneRecentSends = _phoneRateLimitTracker[phoneNumber];
                if (phoneRecentSends.Count >= _options.MaxSendPerHourPerPhone)
                {
                    _logger.LogWarning("手机号 {Phone} 发送频率超出限制，每小时最大: {Limit}", 
                        MaskPhoneNumber(phoneNumber), _options.MaxSendPerHourPerPhone);
                    return false;
                }

                return true;
            }
        }

        /// <summary>
        /// 记录发送尝试
        /// </summary>
        private void RecordSendAttempt(string phoneNumber)
        {
            if (!_options.EnableRateLimit)
                return;

            lock (_rateLimitLock)
            {
                var now = DateTime.UtcNow;

                // 记录全局发送
                var providerKey = "global";
                if (!_rateLimitTracker.ContainsKey(providerKey))
                    _rateLimitTracker[providerKey] = new List<DateTime>();
                _rateLimitTracker[providerKey].Add(now);

                // 记录手机号发送
                if (!_phoneRateLimitTracker.ContainsKey(phoneNumber))
                    _phoneRateLimitTracker[phoneNumber] = new List<DateTime>();
                _phoneRateLimitTracker[phoneNumber].Add(now);
            }
        }

        /// <summary>
        /// 清理过期记录
        /// </summary>
        private void CleanupExpiredRecords(DateTime now)
        {
            // 清理全局记录（保留1分钟内的）
            foreach (var key in _rateLimitTracker.Keys.ToList())
            {
                var oneMinuteAgo = now.AddMinutes(-1);
                _rateLimitTracker[key] = _rateLimitTracker[key]
                    .Where(time => time > oneMinuteAgo)
                    .ToList();

                if (_rateLimitTracker[key].Count == 0)
                    _rateLimitTracker.Remove(key);
            }

            // 清理手机号记录（保留1小时内的）
            foreach (var key in _phoneRateLimitTracker.Keys.ToList())
            {
                var oneHourAgo = now.AddHours(-1);
                _phoneRateLimitTracker[key] = _phoneRateLimitTracker[key]
                    .Where(time => time > oneHourAgo)
                    .ToList();

                if (_phoneRateLimitTracker[key].Count == 0)
                    _phoneRateLimitTracker.Remove(key);
            }
        }

        /// <summary>
        /// 获取有序的提供商列表
        /// </summary>
        private List<ISmsProvider> GetOrderedProviders()
        {
            var orderedProviders = new List<ISmsProvider>();

            // 优先使用默认提供商
            if (_providers.TryGetValue(_options.DefaultProvider.ToLower(), out var defaultProvider))
            {
                orderedProviders.Add(defaultProvider);
            }

            // 添加其他提供商作为备选
            if (_options.EnableFailover)
            {
                foreach (var provider in _providers.Values)
                {
                    if (provider != defaultProvider)
                    {
                        orderedProviders.Add(provider);
                    }
                }
            }

            return orderedProviders;
        }

        /// <summary>
        /// 带重试机制的发送
        /// </summary>
        private async Task<SmsSendResult> SendWithRetry(ISmsProvider provider, SmsMessage message)
        {
            for (int attempt = 0; attempt <= _options.RetryCount; attempt++)
            {
                try
                {
                    SmsSendResult result;
                    
                    if (!string.IsNullOrEmpty(message.TemplateId))
                    {
                        result = await provider.SendTemplateAsync(
                            message.TemplateId, 
                            message.TemplateParams, 
                            message.PhoneNumber, 
                            message.SignName);
                    }
                    else
                    {
                        result = await provider.SendAsync(message);
                    }

                    if (result.Success || attempt == _options.RetryCount)
                    {
                        return result;
                    }

                    if (attempt < _options.RetryCount)
                    {
                        await Task.Delay(_options.RetryIntervalSeconds * 1000);
                    }
                }
                catch (Exception ex)
                {
                    if (attempt == _options.RetryCount)
                    {
                        return new SmsSendResult
                        {
                            Success = false,
                            ErrorMessage = ex.Message,
                            SentAt = DateTime.UtcNow
                        };
                    }

                    if (attempt < _options.RetryCount)
                    {
                        await Task.Delay(_options.RetryIntervalSeconds * 1000);
                    }
                }
            }

            return new SmsSendResult
            {
                Success = false,
                ErrorMessage = "重试次数已用完",
                SentAt = DateTime.UtcNow
            };
        }

        /// <summary>
        /// 手机号码掩码处理
        /// </summary>
        private static string MaskPhoneNumber(string phoneNumber)
        {
            if (string.IsNullOrEmpty(phoneNumber) || phoneNumber.Length < 7)
                return phoneNumber;

            var start = phoneNumber.Substring(0, 3);
            var end = phoneNumber.Substring(phoneNumber.Length - 4);
            var mask = new string('*', phoneNumber.Length - 7);
            
            return start + mask + end;
        }

        #endregion
    }
}
